; The entry point is im2value. The routine needs at least 4608 (0x1200) bytes.
; Well, maybe a bit less depending on where it is located.

; Base address - should be a multiple of 256.
base		equ	6D00h

; U is the base value for addresses contained in the De Bruijn sequence. The
; lowest address will be U*257 and the highest address will be (U+15)*257.
; These correspond to port values of 0 and 254, respectively.
U		equ	(base>>8)+2	; from 6F6Fh to 7E7Eh

		org	base

		; Sorted address to initial value lookup table - 256 entries.
SortedTable:	db	000h, 002h, 004h, 006h, 008h, 00Ah, 00Ch, 00Eh
		db	010h, 012h, 014h, 016h, 018h, 01Ah, 01Ch, 0FFh
		db	001h, 01Fh, 021h, 023h, 025h, 027h, 029h, 02Bh
		db	02Dh, 02Fh, 031h, 033h, 035h, 037h, 039h, 01Eh
		db	003h, 020h, 03Ch, 03Eh, 040h, 042h, 044h, 046h
		db	048h, 04Ah, 04Ch, 04Eh, 050h, 052h, 054h, 03Bh
		db	005h, 022h, 03Dh, 057h, 059h, 05Bh, 05Dh, 05Fh
		db	061h, 063h, 065h, 067h, 069h, 06Bh, 06Dh, 056h
		db	007h, 024h, 03Fh, 058h, 070h, 072h, 074h, 076h
		db	078h, 07Ah, 07Ch, 07Eh, 080h, 082h, 084h, 06Fh
		db	009h, 026h, 041h, 05Ah, 071h, 087h, 089h, 08Bh
		db	08Dh, 08Fh, 091h, 093h, 095h, 097h, 099h, 086h
		db	00Bh, 028h, 043h, 05Ch, 073h, 088h, 09Ch, 09Eh
		db	0A0h, 0A2h, 0A4h, 0A6h, 0A8h, 0AAh, 0ACh, 09Bh
		db	00Dh, 02Ah, 045h, 05Eh, 075h, 08Ah, 09Dh, 0AFh
		db	0B1h, 0B3h, 0B5h, 0B7h, 0B9h, 0BBh, 0BDh, 0AEh
		db	00Fh, 02Ch, 047h, 060h, 077h, 08Ch, 09Fh, 0B0h
		db	0C0h, 0C2h, 0C4h, 0C6h, 0C8h, 0CAh, 0CCh, 0BFh
		db	011h, 02Eh, 049h, 062h, 079h, 08Eh, 0A1h, 0B2h
		db	0C1h, 0CFh, 0D1h, 0D3h, 0D5h, 0D7h, 0D9h, 0CEh
		db	013h, 030h, 04Bh, 064h, 07Bh, 090h, 0A3h, 0B4h
		db	0C3h, 0D0h, 0DCh, 0DEh, 0E0h, 0E2h, 0E4h, 0DBh
		db	015h, 032h, 04Dh, 066h, 07Dh, 092h, 0A5h, 0B6h
		db	0C5h, 0D2h, 0DDh, 0E7h, 0E9h, 0EBh, 0EDh, 0E6h
		db	017h, 034h, 04Fh, 068h, 07Fh, 094h, 0A7h, 0B8h
		db	0C7h, 0D4h, 0DFh, 0E8h, 0F0h, 0F2h, 0F4h, 0EFh
		db	019h, 036h, 051h, 06Ah, 081h, 096h, 0A9h, 0BAh
		db	0C9h, 0D6h, 0E1h, 0EAh, 0F1h, 0F7h, 0F9h, 0F6h
		db	01Bh, 038h, 053h, 06Ch, 083h, 098h, 0ABh, 0BCh
		db	0CBh, 0D8h, 0E3h, 0ECh, 0F3h, 0F8h, 0FCh, 0FBh
		db	01Dh, 03Ah, 055h, 06Eh, 085h, 09Ah, 0ADh, 0BEh
		db	0CDh, 0DAh, 0E5h, 0EEh, 0F5h, 0FAh, 0FDh, 0FEh

		; Interrupt vectors, organized as a De Bruijn sequence B(16,2)
		; A B(16,2) De Bruijn sequence is a wrapping sequence of 256
		; values, formed by 16 symbols, in which every consecutive
		; pair appears exactly once in the sequence, which is what
		; we need. We use the numbers U+0 through U+15 as symbols.
IntVecs:	db	U+00h, U+00h, U+01h, U+00h, U+02h, U+00h, U+03h, U+00h
		db	U+04h, U+00h, U+05h, U+00h, U+06h, U+00h, U+07h, U+00h
		db	U+08h, U+00h, U+09h, U+00h, U+0Ah, U+00h, U+0Bh, U+00h
		db	U+0Ch, U+00h, U+0Dh, U+00h, U+0Eh, U+00h, U+0Fh, U+01h
		db	U+01h, U+02h, U+01h, U+03h, U+01h, U+04h, U+01h, U+05h
		db	U+01h, U+06h, U+01h, U+07h, U+01h, U+08h, U+01h, U+09h
		db	U+01h, U+0Ah, U+01h, U+0Bh, U+01h, U+0Ch, U+01h, U+0Dh
		db	U+01h, U+0Eh, U+01h, U+0Fh, U+02h, U+02h, U+03h, U+02h
		db	U+04h, U+02h, U+05h, U+02h, U+06h, U+02h, U+07h, U+02h
		db	U+08h, U+02h, U+09h, U+02h, U+0Ah, U+02h, U+0Bh, U+02h
		db	U+0Ch, U+02h, U+0Dh, U+02h, U+0Eh, U+02h, U+0Fh, U+03h
		db	U+03h, U+04h, U+03h, U+05h, U+03h, U+06h, U+03h, U+07h
		db	U+03h, U+08h, U+03h, U+09h, U+03h, U+0Ah, U+03h, U+0Bh
		db	U+03h, U+0Ch, U+03h, U+0Dh, U+03h, U+0Eh, U+03h, U+0Fh
		db	U+04h, U+04h, U+05h, U+04h, U+06h, U+04h, U+07h, U+04h
		db	U+08h, U+04h, U+09h, U+04h, U+0Ah, U+04h, U+0Bh, U+04h
		db	U+0Ch, U+04h, U+0Dh, U+04h, U+0Eh, U+04h, U+0Fh, U+05h
		db	U+05h, U+06h, U+05h, U+07h, U+05h, U+08h, U+05h, U+09h
		db	U+05h, U+0Ah, U+05h, U+0Bh, U+05h, U+0Ch, U+05h, U+0Dh
		db	U+05h, U+0Eh, U+05h, U+0Fh, U+06h, U+06h, U+07h, U+06h
		db	U+08h, U+06h, U+09h, U+06h, U+0Ah, U+06h, U+0Bh, U+06h
		db	U+0Ch, U+06h, U+0Dh, U+06h, U+0Eh, U+06h, U+0Fh, U+07h
		db	U+07h, U+08h, U+07h, U+09h, U+07h, U+0Ah, U+07h, U+0Bh
		db	U+07h, U+0Ch, U+07h, U+0Dh, U+07h, U+0Eh, U+07h, U+0Fh
		db	U+08h, U+08h, U+09h, U+08h, U+0Ah, U+08h, U+0Bh, U+08h
		db	U+0Ch, U+08h, U+0Dh, U+08h, U+0Eh, U+08h, U+0Fh, U+09h
		db	U+09h, U+0Ah, U+09h, U+0Bh, U+09h, U+0Ch, U+09h, U+0Dh
		db	U+09h, U+0Eh, U+09h, U+0Fh, U+0Ah, U+0Ah, U+0Bh, U+0Ah
		db	U+0Ch, U+0Ah, U+0Dh, U+0Ah, U+0Eh, U+0Ah, U+0Fh, U+0Bh
		db	U+0Bh, U+0Ch, U+0Bh, U+0Dh, U+0Bh, U+0Eh, U+0Bh, U+0Fh
		db	U+0Ch, U+0Ch, U+0Dh, U+0Ch, U+0Eh, U+0Ch, U+0Fh, U+0Dh
		db	U+0Dh, U+0Eh, U+0Dh, U+0Fh, U+0Eh, U+0Eh, U+0Fh, U+0Fh
		db	U+00h	; The De Bruijn sequence wraps around
				; but the interrupt vectors don't, so we
				; repeat the first byte here.


		; At start, A = 255.
		; At U*257+0000h, A should decrease by 255 before returning,
		;                 resulting in 0.
		; At U*257+0001h, A should decrease by 254, resulting in 1.
		; At U*257+0002h, by 253, resulting in 2.
		; ...
		; At U*257+000Fh, by 240, resulting in 15.
		; (Note there's a gap here)
		; At U*257+0100h, by 239, resulting in 16.
		; At U*257+0101h, by 238, resulting in 17.
		; ...
		; At U*257+0F0Eh, by 1, resulting in 254.
		; At U*257+0F0Fh, it should be returned untouched (255).
		;
		; This way, the value of A will be unique for every possible
		; target address, so all that is left is to find out which
		; original bus value led to that value of A. That's what
		; SortedTable is for.
		;
		; The comment at these addresses indicates what value of the
		; bus led to that address.

		org	U*257+0000h
		dec	a		; 0
		dec	a		; 2
		dec	a		; 4
		dec	a		; 6
		dec	a		; 8
		dec	a		; 10
		dec	a		; 12
		dec	a		; 14
		dec	a		; 16
		dec	a		; 18
		dec	a		; 20
		dec	a		; 22
		dec	a		; 24
		dec	a		; 26
		dec	a		; 28
		;dec	a		; 255
		;jp	U*257+0100h	; Instead of this, we take a shortcut
		sub	240		; by subtracting as many DEC A's as
		ret			; there are remaining, then return.

; Take advantage of the gap between address groups to insert this routine.
; The gap is at least 238 bytes long.

; Bus value finder, using IM2.
;
; Returns bus value in A. Clobbers HL.
; Upon return, interrupts are enabled and IM1 mode is set.

im2value:	ld	a,HIGH IntVecs
		di
		ld	i,a
		ld	a,255		; Prepare initial value
		im	2
		ei
		halt
		im	1
		ei

		ld	l,a		; A is sorted index
		ld	h,HIGH SortedTable
		ld	a,(hl)		; Grab the value for that index
		ret


		org	U*257+0100h
		dec	a		; 1
		dec	a		; 31
		dec	a		; 33
		dec	a		; 35
		dec	a		; 37
		dec	a		; 39
		dec	a		; 41
		dec	a		; 43
		dec	a		; 45
		dec	a		; 47
		dec	a		; 49
		dec	a		; 51
		dec	a		; 53
		dec	a		; 55
		dec	a		; 57
		;dec	a		; 30
		;jp	U*257+0200h	; See comment above
		sub	224		; 30
		ret

		org	U*257+0200h
		dec	a		; 3
		dec	a		; 32
		dec	a		; 60
		dec	a		; 62
		dec	a		; 64
		dec	a		; 66
		dec	a		; 68
		dec	a		; 70
		dec	a		; 72
		dec	a		; 74
		dec	a		; 76
		dec	a		; 78
		dec	a		; 80
		dec	a		; 82
		dec	a		; 84
		sub	208		; 59
		ret

		org	U*257+0300h
		dec	a		; 5
		dec	a		; 34
		dec	a		; 61
		dec	a		; 87
		dec	a		; 89
		dec	a		; 91
		dec	a		; 93
		dec	a		; 95
		dec	a		; 97
		dec	a		; 99
		dec	a		; 101
		dec	a		; 103
		dec	a		; 105
		dec	a		; 107
		dec	a		; 109
		sub	192		; 86
		ret

		org	U*257+0400h
		dec	a		; 7
		dec	a		; 36
		dec	a		; 63
		dec	a		; 88
		dec	a		; 112
		dec	a		; 114
		dec	a		; 116
		dec	a		; 118
		dec	a		; 120
		dec	a		; 122
		dec	a		; 124
		dec	a		; 126
		dec	a		; 128
		dec	a		; 130
		dec	a		; 132
		sub	176		; 111
		ret

		org	U*257+0500h
		dec	a		; 9
		dec	a		; 38
		dec	a		; 65
		dec	a		; 90
		dec	a		; 113
		dec	a		; 135
		dec	a		; 137
		dec	a		; 139
		dec	a		; 141
		dec	a		; 143
		dec	a		; 145
		dec	a		; 147
		dec	a		; 149
		dec	a		; 151
		dec	a		; 153
		sub	160		; 134
		ret

		org	U*257+0600h
		dec	a		; 11
		dec	a		; 40
		dec	a		; 67
		dec	a		; 92
		dec	a		; 115
		dec	a		; 136
		dec	a		; 156
		dec	a		; 158
		dec	a		; 160
		dec	a		; 162
		dec	a		; 164
		dec	a		; 166
		dec	a		; 168
		dec	a		; 170
		dec	a		; 172
		sub	144		; 155
		ret

		org	U*257+0700h
		dec	a		; 13
		dec	a		; 42
		dec	a		; 69
		dec	a		; 94
		dec	a		; 117
		dec	a		; 138
		dec	a		; 157
		dec	a		; 175
		dec	a		; 177
		dec	a		; 179
		dec	a		; 181
		dec	a		; 183
		dec	a		; 185
		dec	a		; 187
		dec	a		; 189
		sub	128		; 174
		ret

		org	U*257+0800h
		dec	a		; 15
		dec	a		; 44
		dec	a		; 71
		dec	a		; 96
		dec	a		; 119
		dec	a		; 140
		dec	a		; 159
		dec	a		; 176
		dec	a		; 192
		dec	a		; 194
		dec	a		; 196
		dec	a		; 198
		dec	a		; 200
		dec	a		; 202
		dec	a		; 204
		sub	112		; 191
		ret

		org	U*257+0900h
		dec	a		; 17
		dec	a		; 46
		dec	a		; 73
		dec	a		; 98
		dec	a		; 121
		dec	a		; 142
		dec	a		; 161
		dec	a		; 178
		dec	a		; 193
		dec	a		; 207
		dec	a		; 209
		dec	a		; 211
		dec	a		; 213
		dec	a		; 215
		dec	a		; 217
		sub	96		; 206
		ret

		org	U*257+0A00h
		dec	a		; 19
		dec	a		; 48
		dec	a		; 75
		dec	a		; 100
		dec	a		; 123
		dec	a		; 144
		dec	a		; 163
		dec	a		; 180
		dec	a		; 195
		dec	a		; 208
		dec	a		; 220
		dec	a		; 222
		dec	a		; 224
		dec	a		; 226
		dec	a		; 228
		sub	80		; 219
		ret

		org	U*257+0B00h
		dec	a		; 21
		dec	a		; 50
		dec	a		; 77
		dec	a		; 102
		dec	a		; 125
		dec	a		; 146
		dec	a		; 165
		dec	a		; 182
		dec	a		; 197
		dec	a		; 210
		dec	a		; 221
		dec	a		; 231
		dec	a		; 233
		dec	a		; 235
		dec	a		; 237
		sub	64		; 230
		ret

		org	U*257+0C00h
		dec	a		; 23
		dec	a		; 52
		dec	a		; 79
		dec	a		; 104
		dec	a		; 127
		dec	a		; 148
		dec	a		; 167
		dec	a		; 184
		dec	a		; 199
		dec	a		; 212
		dec	a		; 223
		dec	a		; 232
		dec	a		; 240
		dec	a		; 242
		dec	a		; 244
		sub	48		; 239
		ret

		org	U*257+0D00h
		dec	a		; 25
		dec	a		; 54
		dec	a		; 81
		dec	a		; 106
		dec	a		; 129
		dec	a		; 150
		dec	a		; 169
		dec	a		; 186
		dec	a		; 201
		dec	a		; 214
		dec	a		; 225
		dec	a		; 234
		dec	a		; 241
		dec	a		; 247
		dec	a		; 249
		sub	32		; 246
		ret

		org	U*257+0E00h
		dec	a		; 27
		dec	a		; 56
		dec	a		; 83
		dec	a		; 108
		dec	a		; 131
		dec	a		; 152
		dec	a		; 171
		dec	a		; 188
		dec	a		; 203
		dec	a		; 216
		dec	a		; 227
		dec	a		; 236
		dec	a		; 243
		dec	a		; 248
		dec	a		; 252
		sub	16		; 251
		ret

		org	U*257+0F00h
		dec	a		; 29
		dec	a		; 58
		dec	a		; 85
		dec	a		; 110
		dec	a		; 133
		dec	a		; 154
		dec	a		; 173
		dec	a		; 190
		dec	a		; 205
		dec	a		; 218
		dec	a		; 229
		dec	a		; 238
		dec	a		; 245
		dec	a		; 250
		dec	a		; 253
		ret			; 254
